---
slug: /quickstart/agent-in-project
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import PartialIde from '../../partials/_ide.mdx';
import VideoPlayer from '../../../src/components/VideoPlayer';

# Add an AI agent to an Existing Project

Now that you've learned the basics of creating an AI agent with Dagger in [Build an AI agent](./index.mdx), its time to apply those lessons to a more realistic use case. In this guide, you will build an AI agent that builds features for an existing project.

For this guide you will start with a Daggerized project. The agent will use the Dagger functions in this project that are already used locally and in CI for testing the project.

## Requirements

This quickstart will take you approximately 10 minutes to complete. You should ideally have completed the AI agent and CI quickstarts and should be familiar with programming in Go, Python, TypeScript, PHP, or Java.

Before beginning, ensure that:

- you have [installed the Dagger CLI](../../install.mdx).
- you have a container runtime installed on your system and running. This can be [Docker](https://docs.docker.com/engine/install/), [Podman](https://podman.io/docs/installation), [nerdctl](https://github.com/containerd/nerdctl), or other Docker-like systems.
- you have [configured](../../configuration/llm.mdx) an LLM provider to use with Dagger.
- you have a GitHub account
- you have completed the [AI agent quickstart](./index.mdx) to learn the basics of LLMs in Dagger.
- you have completed the [CI quickstart](../ci/index.mdx) to a Daggerize a project.

## Inspect the example application

This quickstart uses the [Daggerized project from the CI quickstart](../ci/index.mdx). To verify that your project is in the correct state, change to the project's working directory and list the available Dagger Functions:

```shell
cd hello-dagger
dagger functions
```

This should show:

```
Name        Description
build       Build the application container
build-env   Build a ready-to-use development environment
publish     Publish the application container after building and testing it on-the-fly
test        Return the result of running unit tests
```

## Create a workspace for the agent

The goal of this quickstart is to create an agent to interact with the existing codebase and add features to it. This means that the agent needs the ability to list, read and write files in the project directory.

To give the agent these tools, create a Dagger submodule called `workspace`. This module will have Dagger Functions to list, read, and write files. The agent can use these Dagger Functions to interact with the codebase. By giving the agent a module with a limited set of tools, the agent has less room for error and will be more successful at its tasks.

<Tabs groupId="language" queryString="sdk">
    <TabItem value="go" label="Go">
    Start by creating the submodule:

    ```shell
    dagger init --sdk=go .dagger/workspace
    ```

    Replace the `.dagger/workspace/main.go` file with the following contents:
    ```go file=./snippets/part2/workspace/go/main.go
    ```
    </TabItem>
    <TabItem value="python" label="Python">
    Start by creating the submodule:

    ```shell
    dagger init --sdk=python .dagger/workspace
    ```

    Replace the `.dagger/workspace/src/workspace/main.py` file with the following contents:
    ```python file=./snippets/part2/workspace/python/src/workspace/main.py
    ```
    </TabItem>
    <TabItem value="typescript" label="Typescript">
    Start by creating the submodule:

    ```shell
    dagger init --sdk=typescript .dagger/workspace
    ```

    Replace the `.dagger/workspace/src/index.ts` file with the following contents:
    ```typescript file=./snippets/part2/workspace/typescript/src/index.ts
    ```
    </TabItem>
    <TabItem value="php" label="PHP">
    Start by creating the submodule:

    ```shell
    dagger init --sdk=php .dagger/workspace
    ```

    Replace the `.dagger/workspace/src/Workspace.php` file with the following contents:
    ```php file=./snippets/part2/workspace/php/src/Workspace.php
    ```
    </TabItem>
    <TabItem value="java" label="Java">
    Start by creating the submodule:

    ```shell
    dagger init --sdk=java .dagger/workspace
    ```

    Replace the `.dagger/workspace/src/main/java/io/dagger/modules/workspace/Workspace.java` file with the following contents:
    ```java file=./snippets/part2/workspace/java/src/main/java/io/dagger/modules/workspace/Workspace.java
  ```
</TabItem>
</Tabs>

In this Dagger module, each Dagger Function performs a different operation:
- The `read-file` Dagger Function reads a file in the workspace.
- The `write-file` Dagger Function writes a file to the workspace.
- The `list-files` Dagger Function lists all the files in the workspace.
- The `test` Dagger Function runs the tests on the files in the workspace.

See the functions of the new workspace module:

```shell
dagger -m .dagger/workspace functions
```

This should list the following functions:

```
Name         Description
list-files   List all of the files in the Workspace
read-file    Read a file in the Workspace
source       the workspace source code
test         Return the result of running unit tests
write-file   Write a file to the Workspace
```

Now install the new submodule as a dependency to the main module:

```shell
dagger install ./.dagger/workspace
```

## Create an agentic function

This agent will make changes to the application and use the existing `test` function from the Daggerized CI pipeline to validate the changes.

<Tabs groupId="language" queryString="sdk">
    <TabItem value="go" label="Go">
        Add the following new function to the main dagger module in `.dagger/main.go`:

        ```go file=./snippets/part2/agent/go/agent.go.snippet
        ```
    </TabItem>
    <TabItem value="python" label="Python">
        Add the following new function to the main dagger module in `.dagger/src/hello_dagger/main.py`:

        ```python file=./snippets/part2/agent/python/agent.py.snippet
        ```
    </TabItem>
    <TabItem value="typescript" label="Typescript">
        Add the following new function to the main dagger module in `.dagger/src/index.ts`:

        ```typescript file=./snippets/part2/agent/typescript/agent.ts.snippet
        ```
    </TabItem>
    <TabItem value="php" label="PHP">
    Add the following new function to the main dagger module in `.dagger/src/HelloDagger.php`:

    ```php file=./snippets/part2/agent/php/agent.php.snippet
    ```
    </TabItem>
    <TabItem value="java" label="Java">
        Add the following new function to the main dagger module in `.dagger/src/main/java/io/dagger/modules/hellodagger/HelloDagger.java`:

        ```java file=./snippets/part2/agent/java/agent.java.snippet
        ```

        Be sure to add imports for the following:

        ```Java
import io.dagger.client.Client;
import io.dagger.client.Env;
import io.dagger.client.File;
import io.dagger.client.LLM;
import io.dagger.client.Workspace;
        ```
    </TabItem>
</Tabs>

This code creates a Dagger Function called `develop` that takes an assignment and codebase as input and returns a `Directory` with the modified codebase containing the completed assignment.

There are a few important points to note here:
- The variable `environment` is the environment to define inputs and outputs for the agent. Each input and output provides a description which acts as a declarative form of prompting.
- Other Dagger module dependencies are automatically detected and made available for use in this environment. In this example, Dagger finds the `workspace` sub-module installed and automatically generates bindings for it: `with-workspace-input` and `with-workspace-output`. These bindings can be used to provide (or retrieve) the workspace to the agent.
- The LLM is supplied with a prompt file instead of an inline prompt. By separating the prompt from the Dagger Function code, it becomes easier to maintain and update the instructions given to the LLM.

The final step is to add the prompt file. Create a file at `.dagger/develop_prompt.md` with the following content:

```
You are a developer on the HelloDagger Vue.js project.
You will be given an assignment and the tools to complete the assignment.
Your assignment is: $assignment

## Constraints
- Before writing code, analyze the Workspace to understand the project.
- Do not make unneccessary changes.
- Always run tests to validate your code changes.
- Do not stop until you have completed the assignment and the tests pass.
```

:::note
This prompt is more structured than the prompt from the first quickstart. The tasks the agent will be asked to complete will be more complex because its making modifications to an existing codebase and will need to understand more context. To create a reliable agent that can operate with more complexity, the prompt structure and tools are extremely important.
:::

To see the new function, run:

```shell
dagger functions
```

## Run the agent

Type `dagger` to launch Dagger Shell in interactive mode.

Check the help text for the new Dagger Function:
```shell
.help develop
```

This should show how to use the `develop` function.

Make sure your LLM has been properly [configured](../../configuration/llm.mdx):

```shell
llm | model
```

This should show the model you've configured to use with your provider.

Call the agent with an assignment:

```shell
develop "make the main page blue"
```

If all goes well, the agent will explore the project to find the correct place to make the changes, write the appropriate changes, and then validate them by calling the `test` function.

:::tip
If the agent misbehaves, try providing more guidance in the prompt file based on what went wrong.
:::

<VideoPlayer src="/img/current_docs/quickstart/agent/develop.webm" alt="Run the agent" />


Since the agent returns a `Directory`, use Dagger Shell to do more with that `Directory`. For example:

```shell
# Save the directory containing the completed assignment to a variable
completed=$(develop "make the main page blue")
```

```shell
# Get a terminal in the build container with the directory
build-env --source $completed | terminal
```

```shell
# Run the app with the updated source code
build --source $completed | as-service | up --ports 8080:80
```

```shell
# Save the changes to your filesystem
$completed | export .
```

```shell
# Exit
exit
```

Now you have built an agent that can write code for your project!

## Deploy the agent to GitHub

The next step is to take this agent and deploy it so that it can run automatically. For this part of the guide, you will configure GitHub so that when you label a GitHub issue with "develop", the agent will automatically pick up the task and open a pull request with its solution.

The following steps require that you used the GitHub template and have your own hello-dagger repository.

### Create the develop-issue function

The `develop-issue` function will use the [github-issue](https://daggerverse.dev/mod/github.com/kpenfound/dag/github-issue@b316e472d3de5bb0e54fe3991be68dc85e33ef38) Dagger module from the [Daggerverse](https://daggerverse.dev). This module provides functions to read GitHub issues and create pull requests.

Install the dependency:

```shell
dagger install github.com/kpenfound/dag/github-issue@b316e472d3de5bb0e54fe3991be68dc85e33ef38
```

<Tabs groupId="language" queryString="sdk">
    <TabItem value="go" label="Go">
    Add the following new function to the main dagger module in `.dagger/main.go`:

    ```go file=./snippets/part3/agent/go/agent.go.snippet
    ```
    </TabItem>
    <TabItem value="python" label="Python">
    Add the following new function to the main dagger module in `.dagger/src/hello_dagger/main.py`:

    ```python file=./snippets/part3/agent/python/agent.py.snippet
    ```
    </TabItem>
    <TabItem value="typescript" label="Typescript">
    Add the following new function to the main dagger module in `.dagger/src/index.ts`:

    ```typescript file=./snippets/part3/agent/typescript/agent.ts.snippet
    ```

    Be sure to add `Secret` to the imports.
    </TabItem>
    <TabItem value="php" label="PHP">
    Add the following new function to the main dagger module in `.dagger/src/HelloDagger.php`:

    ```php file=./snippets/part3/agent/php/agent.php.snippet
    ```

    Be sure to add imports for the following:

    ```php
    use Dagger\Secret;
    ```
    </TabItem>
    <TabItem value="java" label="Java">
    Add the following new function to the main dagger module in `.dagger/src/main/java/io/dagger/modules/hellodagger/HelloDagger.java`:

    ```java file=./snippets/part3/agent/java/agent.java.snippet
    ```

    Be sure to add imports for the following:

    ```java
import io.dagger.client.Secret;
import io.dagger.client.GithubIssue;
    ```
    </TabItem>
</Tabs>

The `develop-issue` function connects the dots in the automation flow. It will be called when a GitHub issue is ready to be developed. Using the `github-issue` dependency, this code will:

- Read the title and body from the GitHub issue
- Use the body as the assignment for the agent
- Open a pull request with the `Directory` returned by the agent

To see the new function, run:

```shell
dagger functions
```

### Create a GitHub Actions workflow

1. GitHub Actions will need the ability to call out to an LLM. This means that you must configure GitHub Actions with the same environment variables that you previously [configured](../../configuration/llm.mdx) locally, this time as repository secrets.

To configure new repository secrets:
- From your GitHub repository, select the Settings tab
- Under Security, expand the section "Secrets and Variables" and select Actions
- Select "New repository secret"
- Create a secret for each variable required for your LLM provider. For example: `GEMINI_API_KEY`

![Configure GitHub Actions repository secrets](/img/current_docs/quickstart/agent/configure_gha_llm.png)

If you signed up for Dagger Cloud, you should also configure a `DAGGER_CLOUD_TOKEN` repository secret to see your GitHub Actions traces in Dagger Cloud.

To find your Dagger Cloud token, navigate to the organization settings page using the cogwheel icon in the top navigation bar. Under the `Tokens` sub-menu, click the eye icon to view the token. You can also use this URL pattern: `https://v3.dagger.cloud/{Your Org Name}/settings?tab=Tokens`

![Get token](/img/current_docs/configuration/get-token.png)

2. The repository also needs to be configured to give GitHub Actions the ability to create pull requests. On the left side, select Actions -> General and find the option "Allow GitHub Actions to create and approve pull requests". Make sure this is enabled.

![Allow GitHub Actions to create pull requests](/img/current_docs/quickstart/agent/configure_gha_prs.png)

3. Create the file `.github/workflows/develop.yml` with the following content:

```yaml file=./snippets/part3/develop.yml
```

This snippet shows an example with Google Gemini by specifying `GEMINI_API_KEY`. Change this to match the repository secrets you created earlier.

This GitHub Actions workflow will call the `develop-issue` function when the label "develop" is added to an issue. The GitHub token passed to the agent has permissions to read issues, write contents, and write pull requests.

4. Commit and push your changes to GitHub:

```shell
git add .
git commit -m'deploy agent to github'
git push
```

### Run the agent in GitHub Actions

1. Create a new GitHub issue in your repository. You can title it "change the page color" with the description "make the main page green".

![Create a GitHub issue](/img/current_docs/quickstart/agent/create_issue.png)

2. Now add the label called "develop" by typing "develop" in the labels input field.

![Add issue label develop](/img/current_docs/quickstart/agent/add_label.png)

3. When the label is added, it triggers the GitHub Actions workflow. See the workflow by clicking the "Actions" tab or by opening Dagger Cloud (if you configured it).

![Watch in actions tab](/img/current_docs/quickstart/agent/watch_actions.png)

4. Once the workflow completes, there will be a new pull request ready to review!

![See the agents PR](/img/current_docs/quickstart/agent/agent_pr.png)

## Next steps

Congratulations! You created an agentic function with a Daggerized project and successfully ran it, both locally and in automatically in GitHub.

We encourage you to [join our awesome community on Discord](https://discord.gg/dagger-io) to introduce yourself and ask questions. And [starring our GitHub repository](https://github.com/dagger/dagger) is always appreciated!
